package cn.edu.swu.book;

import cn.edu.swu.core.BasicServlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload2.core.DiskFileItemFactory;
import org.apache.commons.fileupload2.core.FileItem;
import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@WebServlet(urlPatterns = "/book/*")
public class BookController extends BasicServlet {


    private BookService bookService = null;

    // 上传文件存储目录
    private static final String UPLOAD_DIRECTORY = "upload";

    // 上传配置
    private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 3;  // 3MB
    private static final int MAX_FILE_SIZE      = 1024 * 1024 * 40; // 40MB
    private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 50; // 50MB



    public void init(ServletConfig config) {
        BookRepo repo = new BookRepo();
        bookService = new BookService();
        bookService.setRepo(repo);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.methodRoute(request,response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.methodRoute(request,response);
    }

    private void methodRoute(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        String uri=request.getRequestURI();
        String method=uri.substring(uri.lastIndexOf("/")+1);
        System.out.println(method);

       try {
           if (method.equals("list")) {
               this.list(request, response);
           } else if (method.equals("add")) {
               this.add(request, response);
           }else if (method.equals("delete")){
               this.delete(request,response);
           }else if (method.equals("edit")){
               this.edit(request,response);
           }else if (method.equals("update")){
               this.update(request,response);
           }else if (method.equals("search")){
               this.search(request,response);
           }
       }catch (SQLException | IOException e){
           throw new ServletException(e);
       }
    }


    public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        try {
            List<Book> books = this.bookService.getAll();
            try (Writer writer = response.getWriter()) {
                String table = this.wrapTable(books);
                String page = this.wrapPage(table);
                writer.write(page);
            }


        } catch (SQLException | IOException e) {
            throw new ServletException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }


    public void add(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException, SQLException {
        this.save(request,response);
    }

    public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
        this.save(request, response);
    }






    private void delete(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException, SQLException {
        int id=Integer.parseInt(request.getParameter("id"));
        this.bookService.deleteById(id);
        response.sendRedirect("./list");
    }

    private void edit(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException, SQLException {
        int id=Integer.parseInt(request.getParameter("id"));
        try {
            Book book=this.bookService.getById(id);
            try (Writer writer = response.getWriter()) {
                String form = this.wrapEditForm(book);
                String page = this.wrapPage(form);
                writer.write(page);
            }


        } catch (SQLException | IOException e) {
            throw new ServletException(e);
        }

    }

    public void save(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException,SQLException {
        if (!JakartaServletFileUpload.isMultipartContent(request)) {
            // 如果不是则停止
            Writer writer = response.getWriter();
            writer.write("Error: 表单必须包含 enctype=multipart/form-data");
            writer.flush();
            return;
        }

        // 配置上传参数
        DiskFileItemFactory factory = DiskFileItemFactory
                .builder()
                .setBufferSize(MEMORY_THRESHOLD)
                .get();

        JakartaServletFileUpload upload = new JakartaServletFileUpload(factory);

        // 设置最大文件上传值
        upload.setFileSizeMax(MAX_FILE_SIZE);

        // 设置最大请求值 (包含文件和表单数据)
        upload.setSizeMax(MAX_REQUEST_SIZE);

        // 中文处理
        upload.setHeaderCharset(Charset.forName("UTF-8"));

        // 构造临时路径来存储上传的文件
        // 这个路径相对当前应用的目录
        String uploadPath = request.getServletContext().getRealPath("./")
                + File.separator + UPLOAD_DIRECTORY;

        // 如果目录不存在则创建
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdir();
        }


        try {
            Book book = new Book();
            Charset uft8 = Charset.forName("UTF-8");
            String imageName = UUID.randomUUID().toString();
            // 解析请求的内容提取文件数据
            @SuppressWarnings("unchecked")
            List<FileItem> formItems = upload.parseRequest(request);

            if (formItems != null && formItems.size() > 0) {
                // 迭代表单数据
                for (FileItem item : formItems) {
                    // 处理不在表单中的字段
                    if (!item.isFormField()) {
                        String image = new File(item.getName()).getName();
                        imageName += image.substring(image.lastIndexOf("."));
                        String filePath = uploadPath + File.separator + imageName;
                        File storeFile = new File(filePath);
                        // 在控制台输出文件的上传路径
                        System.out.println(filePath);
                        // 保存文件到硬盘
                        item.write(storeFile.toPath());

                        book.setImage(imageName);

                    } else {
                        if (item.getFieldName().equals("id")) {
                            book.setId(Integer.parseInt(item.getString()));
                        } else if (item.getFieldName().equals("name")) {
                            book.setName(item.getString(uft8));
                        } else if (item.getFieldName().equals("author")) {
                            book.setAuthor(item.getString(uft8));
                        } else if (item.getFieldName().equals("price")) {
                            book.setPrice(Double.valueOf(item.getString(uft8)));
                        } else if (item.getFieldName().equals("memo")) {
                            book.setMemo(item.getString(uft8));
                        } else if (item.getFieldName().equals("publish")) {
                            try {
                                book.setPublish(BookService.simpleDateFormat.parse(item.getString(uft8)));
                            } catch (ParseException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }
                }
            }
            this.bookService.save(book);
            response.sendRedirect("./list");
        } catch (IOException ex) {
            throw new ServletException(ex);
        }
    }



//    private void update(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException, SQLException{
//        int id = Integer.parseInt(request.getParameter("id"));
//        String name = request.getParameter("name");
//        String author = request.getParameter("author");
//        double price = Double.parseDouble(request.getParameter("price"));
//        String memo = request.getParameter("memo");
//        String publish = request.getParameter("publish");
//        String image = String.valueOf(request.getPart("image"));
//
//        try {
//            this.bookService.update(id, name, author, price, memo, publish, image);
//        } catch (SQLException e) {
//            throw new ServletException(e);
//        }
//        response.sendRedirect("./list");
//    }

    private void search(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException, SQLException {
        String key = request.getParameter("key");
        try {
            List<Book> books = this.bookService.search(key);
            try (Writer writer = response.getWriter()) {
                String table = this.wrapTable(books);
                String page = this.wrapPage(table);
                writer.write(page);
            }


        } catch (SQLException | IOException e) {
            throw new ServletException(e);
        }
    }


    private String wrapTable(List<Book> books) {
        StringBuilder sb = new StringBuilder();
        sb.append("<table class='bs'>\n");
        sb.append("<tr><th>编号</th><th>书名</th><th>作者</th><th>价格</th><th>描述</th><th>发行日期</th><th>图片</th><th></th><th></th></tr>\n");
        for (Book book : books) {
            sb.append("<tr>");
            sb.append("<td class='center'>").append(book.getId()).append("</td>");
            sb.append("<td>").append(book.getName()).append("</td>");
            sb.append("<td class='center'>").append(book.getAuthor()).append("</td>");
            sb.append("<td class='center'>").append(book.getPrice()).append("</td>");
            sb.append("<td>").append(book.getMemo()).append("</td>");
            sb.append("<td class='center'>").append(book.getPublish()).append("</td>");
            sb.append("<td class='center'><img class='book-img-thumbnail' src='../upload/").append(book.getImage()).append("'/></td>");
            sb.append("<td class='center'><a href='./delete?id=" + book.getId() + "'>删除</a></td>");
            sb.append("<td class='center'><a href='./edit?id=" + book.getId() + "'>修改</a></td>");
            sb.append("</tr>");
        }
        sb.append("</table>");
        return sb.toString();
    }

    private String wrapEditForm(Book book){
        StringBuilder sb= new StringBuilder();
        sb.append("<center><br>")
                .append("<form action=\"./update\" method=\"post\" enctype=\"multipart/form-data\">")
                .append("<input type=\"hidden\" name=\"id\" value=\""+ book.getId()+"\"><br><br>")
                .append("书名:<input type=\"text\" name=\"name\" value=\""+ book.getName()+"\"><br><br>")
                .append("作者:<input type=\"text\" name=\"author\" value=\""+ book.getAuthor()+"\"><br><br>")
                .append("价格:<input type=\"text\" name=\"price\" value=\""+ book.getPrice()+"\"><br><br>")
                .append("备注:<input type=\"text\" name=\"memo\" value=\""+ book.getMemo()+"\"><br><br>")
                .append("日期:<input type=\"text\" name=\"publish\" value=\""+ book.getPublish()+"\"><br><br>")
                .append("图片:<input type=\"file\" name=\"image\"><br><br>")
                .append("<input type=\"submit\" name=\"submit\" value=\"更新图书\"/>")
                .append("</form>")
                .append("</center>");
                return sb.toString();

    }
}













